package com.cfswt.tasksystem.controller;

import com.cfswt.tasksystem.response.JsonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.runtime.shared.query.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.server.PathParam;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipInputStream;

@Slf4j
@RestController
@RequestMapping("/process")
@Api(tags = "流程定义管理模块")
public class ProcessDefinitionController {
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ProcessRuntime processRuntime;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RuntimeService runtimeService;

    @ApiOperation(value = "流程定义列表")
    @GetMapping("/definitions")
    public JsonResult getProcessDefinitions() {
        List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
        for (ProcessDefinition pd : list) {
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("ID_", pd.getId());
            hashMap.put("SUSPENSION_STATE_", pd.getVersion());
            hashMap.put("NAME_", pd.getName());
            hashMap.put("KEY_", pd.getKey());
            hashMap.put("RESOURCE_NAME_", pd.getResourceName());
            hashMap.put("DEPLOYMENT_ID_", pd.getDeploymentId());
            hashMap.put("VERSION_", pd.getVersion());
            listMap.add(hashMap);
        }
        return JsonResult.ok(listMap);
    }

    @ApiOperation(value = "上传xml代码显示流程图")
    @PostMapping("/uploadStream")
    public JsonResult uploadStream(@RequestParam("processFile") MultipartFile processFile,
                                   @RequestParam("deploymentName") String deploymentName) throws IOException {
        Deployment deploy = null;
        String filename = processFile.getOriginalFilename();
        String extension = FilenameUtils.getExtension(filename);
        InputStream inputStream = processFile.getInputStream();
        if (extension.equals("zip")) {
            ZipInputStream zipInputStream = new ZipInputStream(inputStream);
            repositoryService.createDeployment().addZipInputStream(zipInputStream)
                    .name(deploymentName)
                    .deploy();
        } else {
            deploy = repositoryService.createDeployment().addInputStream(filename, inputStream)
                    .name(deploymentName)
                    .deploy();
            DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
            deploymentBuilder.deploy();
        }
        return JsonResult.ok(deploy.getId() + ":" + filename);
    }

    @ApiOperation(value = "部署xml流程")
    @PostMapping("/uploadXML")
    public JsonResult uploadxml(@RequestBody String xmlBPMN) {
        String fileName = UUID.randomUUID().toString() + ".bpmn";
        String deploymentName = "后端部署名字:" + UUID.randomUUID().toString();
        Deployment createByBPMNJS = repositoryService.createDeployment().addString(fileName, xmlBPMN)
                .name(deploymentName)
                .deploy();
        return JsonResult.ok(createByBPMNJS.getId());
    }

    @ApiOperation(value = "获取流程xml文件")
    @GetMapping("/definitionXML")
    public void definitionsXML(HttpServletResponse response,
                               @RequestParam("deploymentID") String deploymentID,
                               @RequestParam("resourceName") String resourceName) {
        InputStream resource = repositoryService.getResourceAsStream(deploymentID, resourceName);
        try {
            int count = resource.available();
            byte[] bytes = new byte[count];
            response.setContentType("text/xml");
            ServletOutputStream outputStream = response.getOutputStream();
            while (resource.read(bytes) != -1) {
                outputStream.write(bytes);
            }
            System.out.println(outputStream);
            resource.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @ApiOperation(value = "通过pid获取xml代码")
    @GetMapping("/definitionXML/{processInstanceId}")
    public JsonResult getProcessDefinitionXml(@PathVariable String processInstanceId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId)
                .singleResult();
        String processDefinitionId = processInstance.getProcessDefinitionId();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId)
                .singleResult();
        String deploymentId = processDefinition.getDeploymentId();
        String resourceName = processDefinition.getResourceName();
        try (InputStream resource = repositoryService.getResourceAsStream(deploymentId, resourceName)) {
            if (resource == null) {
                return JsonResult.error(2002, "BPMN XML 资源不存在");
            }

            // 4. 将输入流转换为字符串
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = resource.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            String bpmnXml = outputStream.toString(StandardCharsets.UTF_8.name());

            // 5. 返回 JSON 结果
            return JsonResult.ok(bpmnXml);
        } catch (Exception e) {
            return JsonResult.error(2002, "获取 BPMN XML 失败");
        }
    }

    @ApiOperation(value = "获取流程定义列表")
    @GetMapping("deployments")
    public JsonResult deployments() {
        List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
        List<Deployment> list = repositoryService.createDeploymentQuery().list();
        for (Deployment deployment : list) {
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("ID_", deployment.getId());
            hashMap.put("DEPLOY_TIME", deployment.getDeploymentTime());
            hashMap.put("NAME_", deployment.getName());
            hashMap.put("VERSION", deployment.getVersion());
            hashMap.put("KEY_", deployment.getKey());
            listMap.add(hashMap);
        }
        return JsonResult.ok(listMap);
    }

    @ApiOperation(value = "删除流程定义")
    @DeleteMapping("/definiton/{id}")
    public JsonResult deleteDefiniton(@PathVariable String id) {
        System.out.println(id);
        repositoryService.deleteDeployment(id, true);
        return JsonResult.ok();
    }
}
